<?php
// 应用公共文件

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\BeforeValidException;
use think\facade\Filesystem;
use think\facade\Lang;
use think\Model;
use think\Response;
use think\response\Json;
use think\exception\HttpResponseException;

	
	/*
	 * 生成token
	 * $data自己想要保存的数据
	 */

if (!function_exists('sign_token')) {
	//生成验签
	function sign_token($data): string
	{
		$key = '!@bdsfbbf';         //这里是自定义的一个随机字串，应该写在config文件中的，解密时也会用，相当于密钥
		$token['iss'] = ''; //签发者 可选
		$token['aud'] = ''; //接收该JWT的一方，可选
		$token['iat'] = time(); //签发时间
		$token['nbf'] = time(); //某个时间点后才能访问
		$token['exp'] = time() + 60 * 60 * 24 * 30; //token过期时间,按秒算
		$token['uid'] = $data['users_id'];
		
		//根据参数生成了 token
		return JWT::encode($token, $key, "HS256");
	}
}
/*
 * 验证token
 * $token 生成的token值
 */

if (!function_exists('check_token')) {
	//验证token
	function check_token($token): array
	{
		$key = '!@bdsfbbf';
		$status = array("code" => 500);
		try {
			JWT::$leeway = 60; //当前时间减去60，把时间留点余地
			$decoded = JWT::decode($token, new Key($key, 'HS256')); //HS256方式，这里要和签发的时候对应
			
			$arr = (array)$decoded;
			$res['code'] = 200;
			$res['data'] = $arr;
			return $res;
		} catch (SignatureInvalidException $e) { //签名不正确
			$status['msg'] = "签名不正确";
			return $status;
		} catch (BeforeValidException $e) { // 签名在某个时间点之后才能用
			$status['msg'] = "token未生效";
			return $status;
		} catch (ExpiredException $e) { // token过期
			$status['msg'] = "token失效";
			return $status;
		} catch (Exception $e) { //其他错误
			$status['msg'] = "未知错误";
			return $status;
		}
	}
}

	/**
	 * 返回封装后的 API 数据到客户端
	 * @access protected
	 * @param mixed  $msg    提示信息
	 * @param mixed|null $data   要返回的数据
	 * @param int $code   错误码，默认为1
	 * @param string|null $type   输出类型，支持json/xml/jsonp
	 * @param array  $header 发送的 Header 信息
	 * @throws HttpResponseException
	 */
	if (!function_exists('writeJson')) {
		function writeJson($code = 1, $msg = '', $data = "",$type='json',array $header = []): Json
		{
			if (!is_int($code)){
	
				$result = [
					'code' => 1,
					'msg' => $msg,
					'data' => $code
				];
			}else{
			
				$result = [
					'code' => $code,
					'msg' => $msg,
					'data' => $data
				];
			}

			// 如果未设置类型则自动判断
			if (isset($header['statuscode'])) {
				$code = $header['statuscode'];
				unset($header['statuscode']);
			} else {
				//未设置状态码,根据code值判断
				$code = $result['code'] >= 1000 || $result['code'] < 200 ? 200 : $result['code'];
			}
	
			$response = Response::create($result, $type, $code)->header($header);
	
			throw new HttpResponseException($response);
		}
	}

/**
 * 获取重定向最终地址
 */
if (!function_exists('get_redirect_url')) {
	function get_redirect_url($url){
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		// 不需要页面内容
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		//是否连续跳转 看情况开启
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		curl_exec($ch);
		$redirect_url = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
		curl_close($ch);
		return $redirect_url;
	}
}



//http请求
//$data  数组
if (!function_exists('http_request')) {
	function http_request($url, $data=[], $method = 'GET', $header = ['Content-Type: application/json; charset=utf-8'])
	{
		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $url);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0');
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
//        curl_setopt($curl, CURLOPT_HTTPGET, true);
		//获取头部信息
		curl_setopt($curl, CURLOPT_TIMEOUT, 300);
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);//允许请求的链接跳转
		if (strtoupper($method) == 'POST') {
			curl_setopt($curl, CURLOPT_POST, true);
			curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
			curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
		}
		$result = curl_exec($curl);
		$httpcode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);

		if ($httpcode != 200) {
			$result = "服务器连接错误,请稍后再试!";
		}
		curl_close($curl);
		return $result;
	}
}




/**
 * 上传图片
 */
if (!function_exists('upload_files')) {
	function upload_files($files)
	{
		if (is_array($files)) {
			$savename = [];
			foreach ($files as $file) {
				
				$savename[] = DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . Filesystem::disk('public')->putFile('/images', $file, 'sha1');
			}
			$savename = implode(",", $savename);
		} else {
			$savename = DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . Filesystem::disk('public')->putFile('/images', $files, 'sha1');
		}
		
		return $savename;
	}
}

/**
 * 评论递归
 * @param $model
 * @param $pid
 * @return mixed
 */

if (!function_exists('comment_recursion')) {
	function comment_recursion(Model $model, $pid)
	{
		$row = $model->find($pid);
		if ($row['pid']) {
			comment_recursion($model, $row['pid']);
		}
		return $row;
	}
	
}

/**
 * 唯一订单号
 * @return string
 */
if (!function_exists('get_uniqid')) {
	function get_uniqid()
	{
		return date('Ymd') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), ))), 0, 8);
	}
}

if (!function_exists('http_down')) {
	
	function http_down($url = '图片路径', $timeout = 60)
	{
		$img_type = strrchr($url, '.');
		$filename = 'images/' . time() . rand(100000, 999999) . rand(1, 99) . $img_type;
		$path = dirname($filename);
		if (!is_dir($path) && !mkdir($path, 0755, true)) {
			return false;
		}
		$fp = fopen($filename, 'w');
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_FILE, $fp);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		curl_exec($ch);
		curl_close($ch);
		fclose($fp);
		return '/' . $filename;
	}
}

/**
 * 根据起点坐标和终点坐标测距离
 * @param  [array]   $from    [起点坐标(经纬度),例如:array(118.012951,36.810024)]
 * @param  [array]   $to    [终点坐标(经纬度)]
 * @param  [bool]    $km        是否以公里为单位 false:米 true:公里(千米)
 * @param  [int]     $decimal   精度 保留小数位数
 * @return [string]  距离数值
 */
if (!function_exists('get_distance')) {
    function get_distance($from, $to, $km = true, $decimal = 2)
    {
        sort($from);
        sort($to);
        $EARTH_RADIUS = 6370.996; // 地球半径系数

        $distance = $EARTH_RADIUS * 2 * asin(sqrt(pow(sin(($from[0] * pi() / 180 - $to[0] * pi() / 180) / 2), 2) + cos($from[0] * pi() / 180) * cos($to[0] * pi() / 180) * pow(sin(($from[1] * pi() / 180 - $to[1] * pi() / 180) / 2), 2))) * 1000;

        if ($km) {
            $distance = $distance / 1000;
        }

        return round($distance, $decimal);
    }
}

if (!function_exists('__')) {

    /**
     * 获取语言变量值
     * @param string $name 语言变量名
     * @param array  $vars 动态变量值
     * @param string $lang 语言
     * @return mixed
     */
    function __($name, $vars = [], $lang = '')
    {
        if (is_numeric($name) || !$name) {
            return $name;
        }
        if (!is_array($vars)) {
            $vars = func_get_args();
            array_shift($vars);
            $lang = '';
        }
        return Lang::get($name, $vars, $lang);
    }
}
